using System;
using System.Collections;
using Castle.MonoRail.Framework;
using Castle.MonoRail.TestSupport;
using NHibernate;
using NUnit.Framework;
using Rhino.Mocks;
using Rhino.Mocks.Constraints;
using DecisionesInteligentes.iEvalua.Web.Controllers;
using DecisionesInteligentes.iEvalua.Web.Services;
using DecisionesInteligentes.iEvalua.Models;
using DecisionesInteligentes.iEvalua.Helpers;
using DecisionesInteligentes.iEvalua.Tests.Helpers;

namespace DecisionesInteligentes.iEvalua.Tests.Controllers {
	[TestFixture]
	public class LoginControllerMockTestCase : ControllerARMockTestCase<LoginController, User>
	{ 
		protected override void SetupApplication()
		{
			using(new MockScope(session))
			{
				Application application = controller.Application;
				
				Assert.IsNotNull(application);
				Assert.AreEqual(application.Id, 1);
			}
		}
		
		public override void SetUp()
		{
			base.SetUp();
			
			Password password = new Password();
			ISecurityService securityService = new SecurityService(password);
			IAuthenticationService authenticationService = new MockAuthenticationService();
			controller = new LoginController(securityService, authenticationService);
			
			DoApplicationSetup();
		}
		
		[Test]
		public void Login_To_Application_With_Invalid_Username()
		{
			IList users = new ArrayList();
			ICriteria criteria = mocks.CreateMock<ICriteria>();

			using(mocks.Unordered())
			{
				Expect.Call(session.CreateCriteria(typeof(User))).Return(criteria);
				Expect.Call(criteria.Add(null)).Constraints(
					Property.Value("Value", "invalid.user") & Property.Value("PropertyName", "Username")
				).Return(criteria);
				Expect.Call(criteria.Add(null)).Constraints(
					Property.Value("Value", 1) & Property.Value("PropertyName", "ApplicationId")
				).Return(criteria);
				Expect.Call(criteria.List()).Return(users);
			}
			
			mocks.ReplayAll();
			
			using(new MockScope(session))
			{
				PrepareController(controller, "", "Login", "Index");
				controller.Index();

				PrepareController(controller, "", "Login", "Login");
				controller.AuthenticateUser("invalid.user", "mypass", true, "index");
				
				Assert.IsNotNull(controller.Flash["login_message"]);
				Assert.IsNull(controller.Flash["login_username"]);
				
				Assert.AreEqual("/Login/Index.rails", Response.RedirectedTo);
			}
		}
		
		[Test]
		public void Login_To_Application_With_Invalid_Password()
		{
			User user = ModelMocks.GetUser();

			IList users = new ArrayList {
				user
			};

			ICriteria criteria = mocks.CreateMock<ICriteria>();

			using(mocks.Unordered())
			{
				Expect.Call(session.CreateCriteria(typeof(User))).Return(criteria);
				Expect.Call(criteria.Add(null)).Constraints(
					Property.Value("Value", "valid.user") & Property.Value("PropertyName", "Username")
				).Return(criteria);
				Expect.Call(criteria.Add(null)).Constraints(
					Property.Value("Value", 1) & Property.Value("PropertyName", "ApplicationId")
				).Return(criteria);
				Expect.Call(criteria.List()).Return(users);
			}

			mocks.ReplayAll();

			using(new MockScope(session))
			{
				PrepareController(controller, "", "Login", "Index");
				controller.Index();

				PrepareController(controller, "", "Login", "Login");
				controller.AuthenticateUser("valid.user", "invalid.pass", true, "index");

				Assert.IsNotNull(controller.Flash["login_message"]);
				Assert.IsNotNull(controller.Flash["login_username"]);
				
				Assert.AreEqual("/Login/Index.rails", Response.RedirectedTo);
			}
		}
			
		[Test]
		public void Login_To_Application_With_Valid_Username()
		{
			User user = ModelMocks.GetUser();
			
			IList users = new ArrayList {
				user
			};
			
			ICriteria criteria = mocks.CreateMock<ICriteria>();
			
			using(mocks.Unordered())
			{
				Expect.Call(session.CreateCriteria(typeof(User))).Return(criteria);
				Expect.Call(criteria.Add(null)).Constraints(
					Property.Value("Value", "valid.user") & Property.Value("PropertyName", "Username")
				).Return(criteria);
				Expect.Call(criteria.Add(null)).Constraints(
					Property.Value("Value", 1) & Property.Value("PropertyName", "ApplicationId")
				).Return(criteria);
				Expect.Call(criteria.List()).Return(users);
			}
			
			mocks.ReplayAll();
			
			using(new MockScope(session))
			{
				PrepareController(controller, "", "Login", "Index");
				controller.Index();

				PrepareController(controller, "", "Login", "Login");
				controller.AuthenticateUser("valid.user", "mypass", true, "/Login/Index.rails");
				
				Assert.IsNull(controller.Flash["login_message"]);
				Assert.IsNull(controller.Flash["login_username"]);
				
				Assert.AreEqual(Context.CurrentUser, user);
				
				Assert.AreEqual("/Login/Index.rails", Response.RedirectedTo);
			}
		}
	}
}
